home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 April: Mac OS SDK / Dev.CD Apr 99 SDK1.toast / Development Kits / Mac OS USB DDK / Examples / KeyboardModule / KeyboardModule.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-10  |  13.4 KB  |  376 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        KeyboardModule.c
  3.  
  4.     Contains:    HID Module for USB Keyboard
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1997-1999 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <processes.h>
  15. #include <DriverServices.h>
  16. #include <USB.h>
  17.  
  18. #include "KeyboardModule.h"
  19.  
  20. usbKeyboardPBStruct myKeyboardPB;
  21. usbKeyboardPBStruct shimKeyboardPB;
  22.  
  23.  
  24.  
  25. void InitParamBlock(USBReference theInterfaceRef, USBPB * paramblock)
  26. {
  27.     paramblock->usbReference = theInterfaceRef;
  28.     paramblock->pbVersion = kUSBCurrentPBVersion;
  29.     
  30.     paramblock->usb.cntl.WIndex = 0;             
  31.     paramblock->usb.cntl.WValue = 0;
  32.     
  33.     paramblock->usbBuffer = nil;        
  34.     paramblock->usbActCount = 0;
  35.     paramblock->usbReqCount = 0;
  36.     paramblock->usbFlags = 0;
  37.     paramblock->usbOther = 0;
  38.     
  39.     paramblock->usbStatus = noErr;
  40. }
  41.  
  42. static Boolean immediateError(OSStatus err)
  43. {
  44.     return((err != kUSBPending) && (err != noErr) );
  45. }
  46.  
  47. void KeyboardInitiateTransaction(USBPB *pb)
  48. {
  49. register usbKeyboardPBStruct *pKeyboardPB;
  50. OSStatus myErr;
  51.  
  52.     pKeyboardPB = (usbKeyboardPBStruct *)(pb);
  53.     pKeyboardPB->transDepth++;
  54.     if (pKeyboardPB->transDepth < 0)
  55.     {
  56.         USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": transDepth < 0 (initiation)", pKeyboardPB->pb.usbRefcon );
  57.     }
  58.     
  59.     if (pKeyboardPB->transDepth > 1)
  60.     {
  61.         USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": transDepth > 1 (initiation)", pKeyboardPB->pb.usbRefcon );
  62.     }
  63.     
  64.     if (pKeyboardPB->driverRemovalPending)
  65.     {
  66.         pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  67.         return;
  68.     }
  69.     
  70.     switch(pKeyboardPB->pb.usbRefcon & ~kRetryTransaction)
  71.     {
  72.         case kSetKeyboardLEDs:
  73.             InitParamBlock(pKeyboardPB->interfaceRef, &pKeyboardPB->pb);
  74.             
  75.             pKeyboardPB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);            
  76.             
  77.             pKeyboardPB->pb.usb.cntl.BRequest = kHIDRqSetReport;
  78.             pKeyboardPB->pb.usb.cntl.WValue = (kHIDRtOutputReport << 8); 
  79.             pKeyboardPB->pb.usb.cntl.WIndex = pKeyboardPB->interfaceDescriptor.interfaceNumber;
  80.             
  81.             pKeyboardPB->pb.usbBuffer = (Ptr)&pKeyboardPB->hidReport[0];
  82.             pKeyboardPB->pb.usbReqCount = 1;
  83.                 
  84.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  85.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  86.             
  87.             myErr = USBDeviceRequest(&pKeyboardPB->pb);
  88.             if(immediateError(myErr))
  89.             {
  90.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": kSetKeyboardLEDs - immediate error", myErr);
  91.             }
  92.             break;
  93.  
  94.         case kConfigureInterface:
  95.             InitParamBlock(pKeyboardPB->interfaceRef, &pKeyboardPB->pb);
  96.             
  97.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  98.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  99.             
  100.             myErr = USBConfigureInterface( &pKeyboardPB->pb );
  101.             if(immediateError(myErr))
  102.             {
  103.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": kConfigureInterface - immediate error", myErr);
  104.                 pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  105.             }
  106.             break;
  107.         
  108.         case kSetProtocol:
  109.             InitParamBlock(pKeyboardPB->interfaceRef, &pKeyboardPB->pb);
  110.             
  111.             pKeyboardPB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);            
  112.             pKeyboardPB->pb.usb.cntl.BRequest = kHIDRqSetProtocol;
  113.             pKeyboardPB->pb.usb.cntl.WValue = kHIDBootProtocolValue; 
  114.             pKeyboardPB->pb.usb.cntl.WIndex = pKeyboardPB->interfaceDescriptor.interfaceNumber;
  115.             
  116.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  117.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  118.         
  119.             myErr = USBDeviceRequest(&pKeyboardPB->pb);
  120.             if (immediateError(myErr))
  121.             {
  122.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": kSetProtocol - immediate error", myErr);
  123.             }
  124.             break;
  125.             
  126.         case kSetIdleRequest:
  127.             InitParamBlock(pKeyboardPB->interfaceRef, &pKeyboardPB->pb);
  128.             
  129.             pKeyboardPB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);            
  130.             
  131.             pKeyboardPB->pb.usb.cntl.BRequest = kHIDRqSetIdle;
  132.             pKeyboardPB->pb.usb.cntl.WValue = ((24/4)<<8);                 // force a read completion if idle for more than 24ms
  133.             pKeyboardPB->pb.usb.cntl.WIndex = pKeyboardPB->interfaceDescriptor.interfaceNumber;
  134.             
  135.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  136.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  137.  
  138.             myErr = USBDeviceRequest(&pKeyboardPB->pb);
  139.             if(immediateError(myErr))
  140.             {
  141.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": kSetIdleRequest - immediate error", myErr);
  142.             }
  143.             break;
  144.  
  145.         case kFindPipe:
  146.             InitParamBlock(pKeyboardPB->interfaceRef, &pKeyboardPB->pb);
  147.             
  148.             pKeyboardPB->pb.usbFlags = kUSBIn;
  149.             pKeyboardPB->pb.usbClassType = kUSBInterrupt;
  150.             
  151.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  152.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  153.         
  154.             myErr = USBFindNextPipe( &pKeyboardPB->pb );
  155.             if((immediateError(myErr)) || (pKeyboardPB->pb.usbBuffer == nil))
  156.             {
  157.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": kFindPipe - immediate error", myErr);
  158.                 pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  159.             }
  160.             break;
  161.         
  162.         case kReadInterruptPipe:
  163.             InitParamBlock(pKeyboardPB->pipeRef, &pKeyboardPB->pb);
  164.  
  165.             pKeyboardPB->pb.usbBuffer = (Ptr)pKeyboardPB->hidReport;
  166.             pKeyboardPB->pb.usbReqCount = 0x08;
  167.             pKeyboardPB->pb.usb.cntl.WIndex = pKeyboardPB->interfaceDescriptor.interfaceNumber;    
  168.             
  169.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  170.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  171.         
  172.             myErr = USBIntRead(&pKeyboardPB->pb);
  173.             if(immediateError(myErr))
  174.             {
  175.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": kReadInterruptPipe - immediate error", myErr);
  176.             }
  177.             break;
  178.             
  179.         case kClearFeature:
  180.             USBExpertStatus(pKeyboardPB->interfaceRef, kKeyboardModuleName": Do a clear feature on the interrupt endpoint", pKeyboardPB->pipeRef);
  181.             InitParamBlock(pKeyboardPB->pipeRef, &pKeyboardPB->pb);
  182.             pKeyboardPB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBEndpoint);
  183.             
  184.             pKeyboardPB->pb.usb.cntl.BRequest = kUSBRqClearFeature;
  185.             pKeyboardPB->pb.usb.cntl.WValue = kUSBFeatureEndpointStall;
  186.             
  187.             pKeyboardPB->pb.usbFlags = kUSBAddressRequest;                /* kUSBAddressRequest asks the USL to do a translation of piperef to endpoint number */
  188.  
  189.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  190.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  191.  
  192.             myErr = USBDeviceRequest(pb);
  193.             if(immediateError(myErr))
  194.             {
  195.                 USBExpertFatalError(pKeyboardPB->pb.usbReference, kUSBInternalErr, kKeyboardModuleName": kClearFeature - immediate error", myErr);
  196.             }
  197.             break;
  198.                 
  199.         default:
  200.             USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName" - Transaction completed with bad refcon value", pKeyboardPB->pb.usbRefcon );
  201.             pKeyboardPB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  202.             break;
  203.     }
  204.     
  205. // At this point the control is returned to the system.  If a USB transaction
  206. // has been initiated, then it will call the Completion proc
  207. // (below) to handle the results of the transaction.
  208. }
  209.  
  210. void KeyboardCompletionProc(USBPB *pb)
  211. {
  212. unsigned char    * errstring;
  213. register usbKeyboardPBStruct *pKeyboardPB;
  214. USBPipeState pipeState;
  215.  
  216.     pKeyboardPB = (usbKeyboardPBStruct *)(pb);
  217.     pKeyboardPB->transDepth--;
  218.     if (pKeyboardPB->transDepth < 0)
  219.     {
  220.         USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": transDepth < 0 (completion)", pKeyboardPB->pb.usbRefcon );
  221.     }
  222.     
  223.     if (pKeyboardPB->transDepth > 1)
  224.     {
  225.         USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": transDepth > 1 (completion)", pKeyboardPB->pb.usbRefcon );
  226.     }
  227.     
  228.     if(pKeyboardPB->pb.usbStatus != noErr)                                                    // was there an error?
  229.     {
  230.         switch(pKeyboardPB->pb.usbRefcon & 0x0fff)                                            // yes, so show where the error occurred
  231.         {
  232.             case kSetKeyboardLEDs:              errstring = kKeyboardModuleName": Error during kSetKeyboardLEDs"; break;
  233.             case kSetProtocol:                    errstring = kKeyboardModuleName": Error during kSetProtocol"; break;
  234.             case kSetIdleRequest:                  errstring = kKeyboardModuleName": Error during kSetIdleRequest"; break;
  235.             case kConfigureInterface:            errstring = kKeyboardModuleName": Error during kConfigureInterface"; break;
  236.             case kFindPipe:                      errstring = kKeyboardModuleName": Error during kFindPipe"; break;
  237.             case kReadInterruptPipe:              errstring = kKeyboardModuleName": Error during kReadInterruptPipe"; break;
  238.             case kClearFeature:                  errstring = kKeyboardModuleName": Error during kClearFeature"; break;
  239.             default:                              errstring = kKeyboardModuleName": Error occurred, but state is unknown"; break;
  240.         };
  241.         USBExpertFatalError(pKeyboardPB->interfaceRef, pKeyboardPB->pb.usbStatus, errstring, (pKeyboardPB->pb.usbRefcon & 0x0fff));
  242.         
  243.         pKeyboardPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);                // set up to retry the transaction
  244.         pKeyboardPB->pb.usbRefcon |= kRetryTransaction;
  245.         pKeyboardPB->retryCount--;
  246.         
  247.         if ((!pKeyboardPB->retryCount)    || (pKeyboardPB->pb.usbStatus == kUSBAbortedError))    // have we exhausted the retries?
  248.         {                                                                                    // or received an abort?
  249.             USBExpertStatus(pKeyboardPB->interfaceRef, kKeyboardModuleName": Pipe abort or unable to recover from error", pKeyboardPB->interfaceRef);
  250.             pKeyboardPB->pb.usbRefcon = kReturnFromDriver;                                    // if so, just exit.
  251.             pKeyboardPB->intPipeAborted = true;                                                
  252.         }
  253.         else                                                                                // if it didn't abort and there's retries left, then...
  254.         {
  255.             if (pKeyboardPB->pipeRef)                                                        // check if the pipe is open.
  256.             {
  257.                 USBGetPipeStatusByReference(pKeyboardPB->pipeRef, &pipeState);                // yes, so what it's state?
  258.                 if (pipeState != kUSBActive)                                                // if it's not active, try to clear it.  It might be stalled...
  259.                 {
  260.                     USBExpertStatus(pKeyboardPB->interfaceRef, kKeyboardModuleName": Pipe is open and stalled, clearing stall...", pKeyboardPB->interfaceRef);
  261.                     USBClearPipeStallByReference(pKeyboardPB->pipeRef);
  262.                 }
  263.             }
  264.         }
  265.     }
  266.     else
  267.     {
  268.         pKeyboardPB->pb.usbRefcon &= ~kRetryTransaction;
  269.         pKeyboardPB->retryCount = kKeyboardRetryCount;
  270.     }
  271.  
  272.     if (pKeyboardPB->pb.usbRefcon & kCompletionPending)             
  273.     {                                                
  274.         pKeyboardPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  275.         switch(pKeyboardPB->pb.usbRefcon)
  276.         {
  277.             case kSetKeyboardLEDs:
  278.                 pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  279.                 break;
  280.                 
  281.             case kConfigureInterface:
  282.                 pKeyboardPB->pb.usbRefcon = kSetProtocol;
  283.                 break;
  284.                 
  285.             case kSetProtocol:
  286.                 pKeyboardPB->pb.usbRefcon = kFindPipe;
  287.                 break;
  288.                 
  289.             case kSetIdleRequest:
  290.                 pKeyboardPB->pb.usbRefcon = kFindPipe;
  291.                 break;
  292.                 
  293.             case kFindPipe:
  294.                 pKeyboardPB->pipeRef = pKeyboardPB->pb.usbReference;
  295.                 pKeyboardPB->pb.usbRefcon = kReadInterruptPipe;
  296.                 pKeyboardPB->keyboardReady = true;
  297.                 shimKeyboardPB.keyboardReady = true;
  298.                 break;
  299.                 
  300.             case kReadInterruptPipe:
  301.                 NotifyRegisteredHIDUser(pKeyboardPB->hidDeviceType, pKeyboardPB->hidReport);
  302.                 pKeyboardPB->pb.usbRefcon = kReadInterruptPipe;
  303.                 break;
  304.                 
  305.             case kClearFeature:
  306.                 pKeyboardPB->pb.usbRefcon = kReadInterruptPipe;
  307.                 break;
  308.                 
  309.             default:
  310.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName" - Transaction completed with bad refcon value", pKeyboardPB->pb.usbRefcon );
  311.                 pKeyboardPB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  312.                 break;
  313.         }
  314.     }
  315.     if (!(pKeyboardPB->pb.usbRefcon & kReturnFromDriver) && (!pKeyboardPB->driverRemovalPending))
  316.         KeyboardInitiateTransaction(pb);
  317. }
  318.  
  319.  
  320. void InterfaceEntry(UInt32 interfacenum, USBInterfaceDescriptorPtr pInterfaceDescriptor, USBDeviceDescriptorPtr pDeviceDescriptor, USBReference theInterfaceRef)
  321. {
  322. #pragma unused (interfacenum)
  323.  
  324. static Boolean beenThereDoneThat = false;
  325.  
  326.     if(beenThereDoneThat)
  327.     {
  328.         USBExpertFatalError(theInterfaceRef, kUSBInternalErr, kKeyboardModuleName" is not reentrant", 12);
  329.         return;
  330.     }
  331.     beenThereDoneThat = true;
  332.     
  333.     //DebugStr("\pIn Keyboard Module Interface entry routine");
  334.     shimKeyboardPB.driverRemovalPending = false;
  335.     shimKeyboardPB.deviceDescriptor = *pDeviceDescriptor;                
  336.     shimKeyboardPB.interfaceDescriptor = *pInterfaceDescriptor;                
  337.     shimKeyboardPB.transDepth = 0;                            
  338.     shimKeyboardPB.retryCount = kKeyboardRetryCount;
  339.     shimKeyboardPB.pSHIMInterruptRoutine = nil;
  340.     shimKeyboardPB.pSavedInterruptRoutine = nil;
  341.     shimKeyboardPB.interfaceRef = theInterfaceRef;
  342.     shimKeyboardPB.pipeRef = 0;
  343.     shimKeyboardPB.keyboardReady = false;
  344.     shimKeyboardPB.intPipeAborted = false;
  345.     
  346.     InitParamBlock(theInterfaceRef, &shimKeyboardPB.pb);
  347.     shimKeyboardPB.pb.pbLength = sizeof(usbKeyboardPBStruct);
  348.     shimKeyboardPB.pb.usbRefcon = 0;                
  349.  
  350.     myKeyboardPB.driverRemovalPending = false;
  351.     myKeyboardPB.deviceDescriptor = *pDeviceDescriptor;                
  352.     myKeyboardPB.interfaceDescriptor = *pInterfaceDescriptor;                
  353.     myKeyboardPB.transDepth = 0;                            
  354.     myKeyboardPB.retryCount = kKeyboardRetryCount;
  355.     myKeyboardPB.pSHIMInterruptRoutine = nil;
  356.     myKeyboardPB.pSavedInterruptRoutine = nil;
  357.     myKeyboardPB.interfaceRef = theInterfaceRef;
  358.     myKeyboardPB.pipeRef = 0;
  359.     myKeyboardPB.keyboardReady = false;
  360.     myKeyboardPB.intPipeAborted = false;
  361.  
  362.     myKeyboardPB.sendRawReportFlag = false;
  363.     myKeyboardPB.hidEmulationInit = false;
  364.     
  365.     InitParamBlock(theInterfaceRef, &myKeyboardPB.pb);
  366.     myKeyboardPB.pb.pbLength = sizeof(usbKeyboardPBStruct);
  367.     myKeyboardPB.pb.usbRefcon = kConfigureInterface;                    
  368.     
  369.     
  370.     USBHIDControlDevice(kHIDEnableDemoMode,0);
  371.     KeyboardInitiateTransaction(&myKeyboardPB.pb);
  372. }
  373.  
  374.  
  375.  
  376.